/*
* Copyright © Shanghai Awinic Technology Co., Ltd. 2020-2020. All rights reserved.
* Description: AFE driver related library function files.
* Date： 20201126
* Awinic_Version： aw_soc_driver_v1.0.0
*/
#include "compile_option.h"
#ifdef AW_86802

#include "aw8680x_global.h"

#ifdef AFE_TEST
	AW_U16 g_afe_buff[ADC_CHANNEL] = {0};	// g_afe_buff
#endif
/**
  * @brief  AFE interrupt number configuration function
  * @param  afe_irq_pri_e is used to set interrupt priority
  * @retval None
  */
static void afe_irq_config(IRQ_PRI_E afe_irq_pri_e)
{
	NVIC_EnableIRQ(IRQ_AFE0); // Enable Interrupt
	NVIC_SetPriority(IRQ_AFE0, afe_irq_pri_e); // Set Interrupt Priority
}

/**
  * @brief  AFE channel configuration function
  * @param  AFE pointer to a AFE_HANDLE_TYPE_S structure that contains
  *         the configuration information for the specified AFE.
  * @retval RET_STATUS_E status
  */
static RET_STATUS_E afe_channel_config(AFE_HANDLE_TYPE_S *p_afe_lib)
{
	AW_U32 i = 0;
	__IO AW_U32 temp_flag = AW_NUM_NULL;

	/* Check the AFE handle allocation */
	if (p_afe_lib == AW_NULL) {
		return RET_ERROR;
	}

	for (i = 0; i < ADC_CHANNEL; i++) {
		/* Configuration ADC configuration Register0 */
		temp_flag = p_afe_lib->init_s.afe_adch_cr0_s[i].pd_ainn_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].pd_ainp_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].pd_swin_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].en_diff_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].dmof_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].red_os_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].sn_mux_e |
					p_afe_lib->init_s.afe_adch_cr0_s[i].sp_mux_e;
		AFE->ADC_CHX[i].ADCH_CR0 = temp_flag;

		/* Configuration ADC configuration Register1 */
		temp_flag = p_afe_lib->init_s.afe_adch_cr1_s[i].gain_pga2_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].gain_pga1_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].pd_filter_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].pd_pga2_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].pd_pga1_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].en_pga_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].inv_ad_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].adc_ibias_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].vcm_adj_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].vref_gen_sel_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].vref_sel_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].bw_filter_e |
					p_afe_lib->init_s.afe_adch_cr1_s[i].pga_ibiase_e;
		AFE->ADC_CHX[i].ADCH_CR1 = temp_flag;
		/* Configuration DAC configuration Register */
		temp_flag = p_afe_lib->init_s.dac_cr_s[i].vdac_range_e |
					p_afe_lib->init_s.dac_cr_s[i].dir_sel_e |
					p_afe_lib->init_s.dac_cr_s[i].dac_vin_e |
					p_afe_lib->init_s.dac_cr_s[i].en_dac_e |
					p_afe_lib->init_s.dac_cr_s[i].en_dac_cal_e;
		AFE->ADC_CHX[i].DACH_CR = temp_flag;
	}

	return RET_OK;
}

/**
  * @brief  AFE initialization function
  * @param  AFE pointer to a AFE_HANDLE_TYPE_S structure that contains
  *         the configuration information for the specified AFE.
  * @retval RET_STATUS_E status
  */
RET_STATUS_E afe_init(AFE_HANDLE_TYPE_S *p_afe_lib)
{
	__IO AW_U32 temp_flag = AW_NUM_NULL;

	/* Check the AFE handle allocation */
	if (p_afe_lib == AW_NULL) {
		return RET_ERROR;
	}

	afe_irq_config(p_afe_lib->afe_irq_pri_e); // set afe interrupt number
	adc_clk_init(p_afe_lib->adc_clkdiv);
	afe_clk_init();
	afe_channel_config(p_afe_lib); // AFE channel configuration

	/* Configure ADC Mode Control register */
	temp_flag = p_afe_lib->init_s.afe_admcr_s.admcr_adie_e |
				p_afe_lib->init_s.afe_admcr_s.admcr_amd_e |
				p_afe_lib->init_s.afe_admcr_s.admcr_trgs_e |
				p_afe_lib->init_s.afe_admcr_s.admcr_valid_ns_e |
				p_afe_lib->init_s.afe_admcr_s.admcr_cal_s_e |
				p_afe_lib->init_s.afe_admcr_s.admcr_unvld_rs_e;
	AFE->ADMCR = temp_flag;
	AFE->ADCHEN = p_afe_lib->adc_channel;
	AFE->ADMCR |= ADMCE_ADC_EN;

	return RET_OK;
}

/**
  * @brief  AFE wait free state function
  * @param  None
  * @retval RET_STATUS_E status
  */
RET_STATUS_E afe_wait_free(void)
{
	AW_S32 afe_timeout = AFE_TIMEOUT;
	while ((AFE->ADSR & ADSR_BUSY) == ADSR_BUSY) {
		if((afe_timeout--) <= 0) {
			return RET_ERROR;
		}
	}
	return RET_OK;
}

/**
  * @brief  AFE wait end state function
  * @param  None
  * @retval RET_STATUS_E status
  */
RET_STATUS_E afe_wait_end(void)
{
	AW_S32 afe_timeout = AFE_TIMEOUT;
	while ((AFE->ADSR & ADSR_ADF) != ADSR_ADF) {
		if((afe_timeout--) <= 0) {
			return RET_ERROR;
		}
	}
	AFE->ADSR = ADSR_ADF;
	return RET_OK;
}

/**
  * @brief  AFE interruption of service function
  * @param  None
  * @retval None
  */
__weak void afe_irq(void)
{
	/* NOTE : This function Should not be modified, when the callback is needed,
			the afe_call could be implemented in the user file
	*/
#ifdef AFE_TEST
	AW_U32 i = 0;

	protect_unlock();
	ADC_SOFT_STOP(); // A/D conversion stop.
	CLK->ADC_CLK_EN = 0;
	CLK->AFE_CLK_EN = 1;
	PWR->VS_EN = 0x00;
	AFE->ADC_CHX[0].ADCH_CR1 &= ~(0x01 << 11);
	AFE->ADC_CHX[1].ADCH_CR1 &= ~(0x01 << 11);

	AFE_CLEAN_STA(); // Clear the existing interruption.
	ADC_SOFT_STOP(); // A/D conversion stop.

	for (i = 0; i < AFE_BUFF_LEN; i++) {
		if (AFE->ADC_CHX[i].ADCH_DR != ADC_THRESHOLD) {
		g_afe_buff[i] = AFE->ADC_CHX[i].ADCH_DR;
	}
}

	CLK->AFE_CLK_EN = 0;
	protect_lock();
#endif
}
#endif
